package com.qianfeng.vhly.youshare.utils;

/**
 * Created with IntelliJ IDEA.
 * User: vhly[FR]
 * Date: 15/2/6
 * Email: vhly@163.com
 */

import android.graphics.Bitmap;
import android.os.Build;
import android.support.v4.util.LruCache;
import android.util.Log;

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.LinkedHashMap;

/**
 * 图片缓存工具，只进行内存图片的管理，如果需要进行文件缓存管理
 * 请调用 FileCache 进行操作。
 */
public class ImageCache {
    private static ImageCache ourInstance;

    public static ImageCache getInstance() {
        if (ourInstance == null) {
            ourInstance = new ImageCache();
        }
        return ourInstance;
    }

    // 1. 声明一级缓存 缓存在内存中有固定的大小，如果缓存超过这个大小限制
    //    删掉最旧的缓存条目，再添加新的内容

    /**
     * 一级缓存采用固定内存尺寸的方式存储部分内容，
     * 当空间不足的时候，采用LRU算法将很少使用、很长时间没有使用的对象替换掉
     */
    private LruCache<String, Bitmap> firstCache;

    // 2. 声明第二级缓存，缓存就直接采用HashMap进行存储，存储的对象是
    //    SoftReference 来引用的对象，HashMap的操作，可以一直添加，
    //    当内存不足的时候，会直接回收，因此可以充分利用内存，尽可能多的
    //    再内存中保存 Bitmap的实例，因为内存访问非常快.

    private HashMap<String, SoftReference<Bitmap>> secondCache;

    private ImageCache() {
        // LruCache 构造方法最大尺寸这个参数代表，当前的缓存在内存中最大占用多少字节
        // Google 建议，LruCache 最大内存字节数 是 当前手机系统可用内存的 八分之一
        long freeMemory = Runtime.getRuntime().freeMemory();
        Log.d("ImageCache", "freeMemory is : " + freeMemory);

        if (freeMemory > 0) {
            freeMemory = freeMemory / 8;
        } else {
            freeMemory = 5 * 1024 * 1024; // 5MB
        }

        firstCache = new LruCache<String, Bitmap>((int) freeMemory) {

            @Override
            protected int sizeOf(String key, Bitmap value) {

                int size = 0;

                // Android 判断版本号
                if (Build.VERSION.SDK_INT >= 19) {
                    size = value.getAllocationByteCount();
                } else {
                    int rowBytes = value.getRowBytes();// 一行的字节数
                    int height = value.getHeight();
                    size = rowBytes * height;
                }

                Log.d("YouShare", "LruCache bitmap size: " + size);

                return size;
            }
        };
        secondCache = new LinkedHashMap<String, SoftReference<Bitmap>>();
    }

    /**
     * 获取内存缓存中指定url地址的图片
     *
     * @param url String 图片地址
     * @return Bitmap 对象
     */
    public Bitmap getImage(String url) {
        Bitmap ret = null;

        if (url != null) {
            // 先从第一级缓存查找，找到，直接返回，未找到
            // 从第二级查找
            ret = firstCache.get(url);
            if (ret == null) { // 第一级没有缓存，查第二级
                if (secondCache.containsKey(url)) {
                    // 如果第二级有url的引用，那么查找内部的数据
                    // 第二级内部数据由于是SoftReference，很可能获取出来的结果就是 null
                    // 因为GC可以把SoftReference 对象释放
                    SoftReference<Bitmap> reference = secondCache.get(url);
                    if (reference != null) {
                        ret = reference.get(); // 获取引用的实际对象
                    }
                }
            }
        }
        return ret;
    }

    /**
     * 更新内存缓存。
     *
     * @param url
     * @param bitmap
     */
    public void putImage(String url, Bitmap bitmap) {
        if (url != null && bitmap != null) {

            Log.d("YouShare", "Put Image to Cache " + url);

            // 更新第二级缓存
            secondCache.put(url, new SoftReference<Bitmap>(bitmap));

            // 更新第一级缓存
            firstCache.put(url, bitmap);
        }
    }
}
